package com.zxw.文件.PDF.util;

import com.itextpdf.text.*;
import com.itextpdf.text.pdf.*;
import com.itextpdf.text.pdf.draw.LineSeparator;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @projectName: ruoyi
 * @package: com.zxw.文件.PDF.util
 * @className: PDFUtil
 * @author: zhangxuewei
 * @description: TODO
 * @date: 2023/9/18 14:31
 * @version: 1.0
 */
@Component
public class PDFUtil {

    public static String fontAddr;

    public static TableCell tableCell = new TableCell();

    @Value("${fontAddr}")
    public void setFontAddr(String fontAddr) {
        PDFUtil.fontAddr = fontAddr;
    }

    public static BaseFont getNormalBaseFont() throws IOException, DocumentException {
        BaseFont bf = BaseFont.createFont(fontAddr, BaseFont.IDENTITY_H, BaseFont.NOT_EMBEDDED);
        return bf;
    }

    public static Font getNormalFont(BaseFont bf) {
        Font font = new Font(bf, 12);
        return font;
    }


    /**
     * 获取创建段落的类
     *
     * @param font
     * @param fontSize 字体大小
     * @throws DocumentException
     */
    public static Paragraph getParagraph(Font font, Float fontSize) {
        if (!ObjectUtils.isEmpty(fontSize)) {
            font.setSize(fontSize);
        }
        // 添加中文内容
        Paragraph paragraph = new Paragraph();
        paragraph.setFont(font);
        return paragraph;
    }

    /**
     * 获取创建段落的类
     *
     * @param font
     * @param fontSize 字体大小
     * @param info     写入信息
     * @throws DocumentException
     */
    public static Paragraph getParagraphAndWrite(Font font, Float fontSize, String info) {
        Paragraph paragraph = getParagraph(font, fontSize);
        // 添加中文内容
        paragraph.add(new Chunk(info));
        return paragraph;
    }


    /**
     * 拼接写入带有颜色的文本
     *
     * @param paragraph       创建段落对象
     * @param info            写入的文本
     * @param backgroundColor 文本背景颜色
     * @return
     */
    public static Paragraph appendWithBackgroundColor(Paragraph paragraph, String info, BaseColor backgroundColor) {
        // 添加中文内容
        Chunk chunk = new Chunk(info);
        if (!ObjectUtils.isEmpty(backgroundColor)) {
            chunk.setBackground(backgroundColor); // 根据索引获取背景颜色
        }
        paragraph.add(chunk);
        return paragraph;
    }

    /**
     * 拼接写入带有颜色的文本结束的方法
     *
     * @param paragraph       创建段落对象
     * @param info            写入的文本
     * @param backgroundColor 文本背景颜色
     * @param document        文档对象
     * @throws DocumentException
     */
    public static void appendWithBackgroundColorEnd(Paragraph paragraph, String info, BaseColor backgroundColor, Document document) throws DocumentException {
        appendWithBackgroundColor(paragraph, info, backgroundColor);
        document.add(paragraph);
    }


    /**
     * 正常书写
     *
     * @param document
     * @param font
     * @param fontSize 字体大小
     * @param info     写入信息
     * @throws DocumentException
     */
    public static void writeParagraph(Document document, Font font, Float fontSize, String info) throws DocumentException {
        if (!ObjectUtils.isEmpty(fontSize)) {
            font.setSize(fontSize);
        }
        // 添加中文内容
        Paragraph paragraph = new Paragraph(info, font);
        document.add(paragraph);
    }


    /**
     * 书写加粗的文字
     *
     * @param document
     * @param bf
     * @param fontSize 字体大小
     * @param info     写入信息
     * @throws DocumentException
     */
    public static void writeBoldParagraph(Document document, BaseFont bf, Float fontSize, String info) throws DocumentException {
        Font font = PDFUtil.getNormalFont(bf);
        font.setStyle(Font.BOLD);
        // 添加中文内容
        writeParagraph(document, font, fontSize, info);
    }


    /**
     * 书写带有颜色的字体
     *
     * @param document
     * @param font
     * @param fontSize
     * @param fontColor
     * @throws DocumentException
     */
    public static void writeColorParagraph(Document document, Font font, Float fontSize, BaseColor fontColor, String info) throws DocumentException {
        if (!ObjectUtils.isEmpty(fontColor))
            font.setColor(fontColor);
        writeParagraph(document, font, fontSize, info);
    }


    /**
     * 书写带有颜色的加粗字体
     *
     * @param document
     * @param bf
     * @param fontSize
     * @param fontColor
     * @throws DocumentException
     */
    public static void writeBoldColorParagraph(Document document, BaseFont bf, float fontSize, BaseColor fontColor, String info) throws DocumentException {
        Font font = PDFUtil.getNormalFont(bf);
        font.setStyle(Font.BOLD);
        writeColorParagraph(document, font, fontSize, fontColor, info);
    }


    /**
     * 书写带有颜色背景的字体
     *
     * @param document
     * @param font
     * @param fontSize
     * @param backgroundColor 背景颜色
     * @param info
     * @throws DocumentException
     */
    public static void writeColorBackgroundParagraph(Document document, Font font, float fontSize, BaseColor backgroundColor, String info) throws DocumentException {
        if (fontSize > 0) {
            font.setSize(fontSize);
        }
        Chunk chunk = new Chunk(info, font);
        chunk.setBackground(backgroundColor);
        Paragraph paragraphcb = new Paragraph();
        paragraphcb.add(chunk);
        document.add(paragraphcb);
    }


    /**
     * 书写带有颜色背景的加粗字体
     *
     * @param document
     * @param font
     * @param fontSize
     * @param backgroundColor
     * @param info
     * @throws DocumentException
     */
    public static void writeBoldColorBackgroundParagraph(Document document, Font font, float fontSize, BaseColor backgroundColor, String info) throws DocumentException {
        font.setStyle(Font.BOLD);
        writeColorBackgroundParagraph(document, font, fontSize, backgroundColor, info);
    }


    /**
     * 书写带有颜色背景的彩色字体
     *
     * @param document
     * @param font
     * @param fontSize
     * @param backgroundColor
     * @param fontColor
     * @param info
     * @throws DocumentException
     */
    public static void writeColorBackgroundColorFontParagraph(Document document, Font font, float fontSize, BaseColor backgroundColor, BaseColor fontColor, String info) throws DocumentException {
        if (fontSize > 0) {
            font.setSize(fontSize);
        }
        font.setColor(fontColor);
        Chunk chunk = new Chunk(info, font);
        chunk.setBackground(backgroundColor);
        Paragraph paragraphcb = new Paragraph();
        paragraphcb.add(chunk);
        document.add(paragraphcb);
    }


    /**
     * 书写带有颜色背景的彩色加粗字体
     *
     * @param document
     * @param font
     * @param fontSize
     * @param backgroundColor
     * @param fontColor
     * @param info
     * @throws DocumentException
     */
    public static void writeBoldColorBackgroundColorFontParagraph(Document document, Font font, float fontSize, BaseColor backgroundColor, BaseColor fontColor, String info) throws DocumentException {
        font.setStyle(Font.BOLD);
        writeColorBackgroundColorFontParagraph(document, font, fontSize, backgroundColor, fontColor, info);
    }


    /**
     * 画线
     *
     * @param document
     * @param percentage 所占页面宽度的百分比
     * @param alignment  对齐方式  如：Element.ALIGN_RIGHT
     * @throws DocumentException
     */
    public static void drawLine(Document document, float percentage, int alignment) throws DocumentException {
        LineSeparator line = new LineSeparator();
        line.setPercentage(percentage);
        line.setAlignment(alignment);
        line.setLineWidth(1);
        document.add(line);
    }

    /**
     * 书写表格
     *
     * @param document
     * @param font
     * @param fontSize
     * @param numColumns
     * @param data
     * @throws DocumentException
     */
    public static void writeTable(Document document, Font font, Float fontSize, int numColumns, BaseColor borderColor, List<Map<Integer, String>> data) throws DocumentException {
        PdfPTable table = new PdfPTable(numColumns); // 3列的表格
        table.setWidthPercentage(100);// 表格将占据整个页面的宽度
        table.setSpacingBefore(10f);// 表格与上面的内容之间将有 10 磅的间距
        table.setSpacingAfter(10f);// 表格与下面的内容之间将有 10 磅的间距
        for (int i = 0; i < data.size(); i++) {
            Map<Integer, String> sortedMap = data.get(i).entrySet()
                    .stream()
                    .sorted(Map.Entry.comparingByKey())
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            Map.Entry::getValue,
                            (e1, e2) -> e1, // 如果有重复键，保留第一个
                            LinkedHashMap::new // 保持顺序
                    ));
            sortedMap.forEach((key, item) -> {
                PdfPCell cell = new PdfPCell(getParagraphAndWrite(font, fontSize, item));
                if (!ObjectUtils.isEmpty(borderColor)) {
                    cell.setBorderColor(borderColor);
                } else {
                    cell.setBorder(PdfPCell.NO_BORDER);
                }
                cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                cell.setPadding(5);
                table.addCell(cell);
            });
        }
        document.add(table);
    }

    /**
     * 书写表格
     *
     * @param document     文档对象
     * @param columnWidths 列宽
     * @param bf           字体基础配置
     * @param borderColor  表格边框颜色
     * @param data
     * @throws DocumentException
     */
    public static void writeTable(Document document, float[] columnWidths, BaseFont bf, BaseColor borderColor, List<Map<Integer, TableCell>> data) throws DocumentException {
        PdfPTable table = new PdfPTable(columnWidths.length); // 3列的表格
        table.setWidthPercentage(100);// 表格将占据整个页面的宽度
        table.setSpacingBefore(10f);// 表格与上面的内容之间将有 10 磅的间距
        table.setSpacingAfter(10f);// 表格与下面的内容之间将有 10 磅的间距
        table.setWidths(columnWidths);
        for (int i = 0; i < data.size(); i++) {
            Map<Integer, TableCell> sortedMap = data.get(i).entrySet()
                    .stream()
                    .sorted(Map.Entry.comparingByKey())
                    .collect(Collectors.toMap(
                            Map.Entry::getKey,
                            Map.Entry::getValue,
                            (e1, e2) -> e1, // 如果有重复键，保留第一个
                            LinkedHashMap::new // 保持顺序
                    ));
            sortedMap.forEach((key, item) -> {
                TableCell tableCell = item;
                Font font = PDFUtil.getNormalFont(bf);
                if (tableCell.isBold())
                    font.setStyle(Font.BOLD);
                if (!ObjectUtils.isEmpty(tableCell.getFontColor()))
                    font.setColor(tableCell.getFontColor());
                if (!ObjectUtils.isEmpty(tableCell.getFontSize()))
                    font.setSize(tableCell.getFontSize());
                Chunk chunk = new Chunk(tableCell.getCellDataInfo(), font);
                if (!ObjectUtils.isEmpty(tableCell.getFontBackgroundColor()))
                    chunk.setBackground(tableCell.getFontBackgroundColor());
                Paragraph paragraph = new Paragraph(chunk);

                PdfPCell cell = new PdfPCell(paragraph);
                if (!ObjectUtils.isEmpty(borderColor))
                    cell.setBorderColor(borderColor);
                else
                    cell.setBorder(PdfPCell.NO_BORDER);
                if (!ObjectUtils.isEmpty(tableCell.getCellBackgroundColor()))
                    cell.setBackgroundColor(tableCell.getCellBackgroundColor());
                if (!ObjectUtils.isEmpty(tableCell.getCellAlign()))
                    cell.setHorizontalAlignment(tableCell.getCellAlign());
                else
                    cell.setHorizontalAlignment(Element.ALIGN_CENTER);
                cell.setVerticalAlignment(Element.ALIGN_MIDDLE);
                cell.setPadding(5);
                table.addCell(cell);
            });
        }
        document.add(table);
    }


}
